using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.U2D;
using UnityEngine;
using UnityEngine.U2D;

// using Object = System.Object;

namespace Editor.AtlasTools
{
    public class AtlasTools
    {
        /// <summary>
        /// 图集配置文件夹路径
        /// </summary>
        private const string AtlasConfigDirPath = "Assets/Editor/AtlasTools/AtlasConfig/";

        /// <summary>
        /// 未分组图集名称
        /// </summary>
        public const string noGroupAtlasName = "NoGroupAtlas";

        /// <summary>
        /// 图集文件夹路径
        /// </summary>
        private const string atlasDirPath = "Assets/MainPackage/Atlas/";

        private const string atlasJsonConfig = "Assets/MainPackage/Config/atlasConfig.json";

        /// <summary>
        /// 图片文件夹路径
        /// </summary>
        private const string spriteDirPath = "Assets/MainPackage/Sprites";

        /// <summary>
        /// 分组过的图片
        /// </summary>
        public static List<Texture> groupedTextures = new List<Texture>();

        public static List<Sprite> noGroupTextures = new List<Sprite>();

        public static List<AtlasConfigWrapper> AtlasConfigWrappers = new List<AtlasConfigWrapper>();
        public static List<string> spriteNames = new List<string>();

        public static void LoadAtlasConfig()
        {
            try
            {
                if (!Directory.Exists(atlasDirPath))
                {
                    Directory.CreateDirectory(atlasDirPath);
                }

                if (!Directory.Exists(AtlasConfigDirPath))
                {
                    Directory.CreateDirectory(AtlasConfigDirPath);
                }
                
                groupedTextures.Clear();
                noGroupTextures.Clear();
                AtlasConfigWrappers.Clear();

                EditorUtility.DisplayProgressBar("Loading Atlas", "Loading configuration...", -1);

                AssetDatabase.GetAllAssetPaths();
                string[] atwGuids = AssetDatabase.FindAssets("", new[] { AtlasConfigDirPath });
                foreach (string guid in atwGuids)
                {
                    string path = AssetDatabase.GUIDToAssetPath(guid);
                    var atlasConfigWrapper = AssetDatabase.LoadAssetAtPath<AtlasConfigWrapper>(path);
                    if (atlasConfigWrapper != null && atlasConfigWrapper.atlasName != noGroupAtlasName) // 剔除未分组的图集配置文件
                    {
                        AtlasConfigWrappers.Add(atlasConfigWrapper);
                    }
                }

                for (int i = 0; i < AtlasConfigWrappers.Count; i++)
                {
                    for (int j = 0; j < AtlasConfigWrappers[i].textureList.Count; j++)
                    {
                        if (!groupedTextures.Contains(AtlasConfigWrappers[i].textureList[j]))
                        {
                            groupedTextures.Add(AtlasConfigWrappers[i].textureList[j]);
                        }
                        else
                        {
                            Debug.LogError("AtlasTools LoadAtlasConfig Error :" +
                                           AtlasConfigWrappers[i].textureList[j].name + " 重复");
                        }
                    }
                    // groupedTexts.AddRange(AtlasConfigWrappers[i].textureList);
                }

                Debug.Log("读取本地图集配置信息:" + AtlasConfigWrappers.Count);

                List<Texture> textures = new List<Texture>();
                if (Directory.Exists(spriteDirPath))
                {
                    // 读取未分组的图片
                    string[] guids = AssetDatabase.FindAssets("t:Texture", new[] { spriteDirPath });
                    foreach (string guid in guids)
                    {
                        string path = AssetDatabase.GUIDToAssetPath(guid);
                        Texture texture = AssetDatabase.LoadAssetAtPath<Texture>(path);
                        if (texture != null)
                        {
                            if (!groupedTextures.Contains(texture))
                            {
                                textures.Add(texture);
                            }

                            if (!spriteNames.Contains(texture.name))
                            {
                                spriteNames.Add(texture.name);
                            }
                            else
                            {
                                Debug.LogError("AtlasTools LoadAtlasConfig Error :" + texture.name + " 重复");
                            }
                        }
                    }

                    Debug.Log("收集未分组的图片 :" + textures.Count);
                }

                // 把未分组图片 分组到 noGroupAtlas 中

                var noGroupConfig = GetNoGroupConfig();
                for (int i = 0; i < textures.Count; i++)
                {
                    if (!noGroupConfig.textureList.Contains(textures[i]))
                    {
                        noGroupConfig.textureList.Add(textures[i]);
                    }
                    // else
                    // {
                    //     Debug.LogError("AtlasTools no Group Error :"+ textures[i].name +" 重复");
                    // }
                }

                noGroupConfig.InitTextures();
                AtlasConfigWrappers.Add(noGroupConfig);
                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();
            }
            catch (Exception e)
            {
                Debug.LogError("LoadAtlasConfig Error :" + e);
                throw;
            }
            finally
            {
                EditorUtility.ClearProgressBar();
            }
        }

        private static AtlasConfigWrapper _noGroupConfig;

        public static AtlasConfigWrapper GetNoGroupConfig()
        {
            if (_noGroupConfig != null)
            {
                return _noGroupConfig;
            }

            _noGroupConfig = AssetDatabase.LoadAssetAtPath<AtlasConfigWrapper>(AtlasConfigDirPath + noGroupAtlasName);
            if (_noGroupConfig == null)
            {
                _noGroupConfig = ScriptableObject.CreateInstance<AtlasConfigWrapper>();
                _noGroupConfig.atlasName = noGroupAtlasName;
                AssetDatabase.CreateAsset(_noGroupConfig, AtlasConfigDirPath + noGroupAtlasName + ".asset");
            }

            if (_noGroupConfig.textureList == null)
            {
                _noGroupConfig.textureList = new List<Texture>();
            }

            return _noGroupConfig;
        }

        /// <summary>
        /// 按文件夹，生成图集配置文件
        /// </summary>
        [MenuItem("AtlasTools/CreateConfigByDirectory")]
        public static void CreateConfigByDir()
        {
            try
            {
                EditorUtility.DisplayProgressBar("Create Atlas Config", "Creating configuration...", -1);

                // 按文件夹生成AtlasConfigWrapper
                string[] folders = AssetDatabase.GetSubFolders(spriteDirPath);
                foreach (string folder in folders)
                {
                    string folderName = Path.GetFileName(folder);

                    // 查找或创建AtlasConfigWrapper
                    string assetPath = $"{AtlasConfigDirPath}{folderName}.asset";
                    AtlasConfigWrapper wrapper = AssetDatabase.LoadAssetAtPath<AtlasConfigWrapper>(assetPath);

                    if (wrapper == null)
                    {
                        wrapper = ScriptableObject.CreateInstance<AtlasConfigWrapper>();
                        wrapper.atlasName = folderName;
                        AssetDatabase.CreateAsset(wrapper, assetPath);
                    }

                    if (wrapper.textureList == null)
                    {
                        wrapper.textureList = new List<Texture>();
                    }

                    // 收集该目录下的所有Texture
                    string[] guids = AssetDatabase.FindAssets("t:Texture", new[] { folder });
                    wrapper.textureList.Clear();
                    foreach (string guid in guids)
                    {
                        string path = AssetDatabase.GUIDToAssetPath(guid);
                        Texture texture = AssetDatabase.LoadAssetAtPath<Texture>(path);
                        if (texture != null)
                        {
                            wrapper.textureList.Add(texture);
                        }
                    }

                    wrapper.InitTextures();
                    Debug.Log("AtlasTools CreateConfigByDir :" + wrapper.atlasName + "  " + wrapper.textureList.Count);
                    EditorUtility.SetDirty(wrapper);
                    AssetDatabase.SaveAssets();
                }

                AssetDatabase.Refresh();
            }
            catch (Exception e)
            {
                Debug.LogError("CreateConfigByDir Error :" + e);
            }
            finally
            {
                EditorUtility.ClearProgressBar();
            }
        }

        /// <summary>
        /// 新建图集配置
        /// </summary>
        /// <param name="atlasName"></param>
        public static AtlasConfigWrapper CreateAtlasConfig(string atlasName)
        {
            string assetPath = $"{AtlasConfigDirPath}{atlasName}.asset";
            if (File.Exists(assetPath))
            {
                EditorUtility.DisplayDialog("AtlasTools", $"AtlasConfig {atlasName} already exists!", "OK");
                return null;
            }

            var wrapper = ScriptableObject.CreateInstance<AtlasConfigWrapper>();
            wrapper.atlasName = atlasName;
            AssetDatabase.CreateAsset(wrapper, assetPath);
            AtlasConfigWrappers.Add(wrapper);
            return wrapper;
        }

        /// <summary>
        /// 删除图集配置
        /// </summary>
        /// <param name="atlasConfigWrapper"></param>
        public static bool DeleteAtlasConfig(AtlasConfigWrapper atlasConfigWrapper)
        {
            if (atlasConfigWrapper != null)
            {
                string assetPath = $"{AtlasConfigDirPath}{atlasConfigWrapper.atlasName}.asset";
                if (atlasConfigWrapper.textureList != null && atlasConfigWrapper.textureList.Count > 0)
                {
                    if (EditorUtility.DisplayDialog("AtlasTools",
                            $"AtlasConfig {atlasConfigWrapper.atlasName} has textures, delete it?", "OK", "Cancel"))
                    {
                        var noGroupConfig = GetNoGroupConfig();
                        AddSpritesToAtlas(noGroupConfig, atlasConfigWrapper.textureList);
                        DeleteAtlasConfigsForce(atlasConfigWrapper);
                        return true;
                    }
                }
                else
                {
                    DeleteAtlasConfigsForce(atlasConfigWrapper);
                }
            }

            return false;
        }

        static void DeleteAtlasConfigsForce(AtlasConfigWrapper atlasConfigWrapper)
        {
            string assetPath = $"{AtlasConfigDirPath}{atlasConfigWrapper.atlasName}.asset";
            if (AtlasConfigWrappers.Contains(atlasConfigWrapper))
            {
                AtlasConfigWrappers.Remove(atlasConfigWrapper);
                AssetDatabase.DeleteAsset(assetPath);
                AssetDatabase.SaveAssets();
            }
            else
            {
                Debug.LogError("AtlasTools DeleteAtlasConfig Error :" + atlasConfigWrapper.atlasName +
                               " 不在 AtlasConfigWrappers 里");
            }
        }

        public static void DeleteSpritesFromAtlas(AtlasConfigWrapper atlasConfigWrapper, List<Texture> textureList)
        {
            for (int i = 0; i < textureList.Count; i++)
            {
                if (atlasConfigWrapper.textureList.Contains(textureList[i]))
                {
                    atlasConfigWrapper.textureList.Remove(textureList[i]);
                }
                else
                {
                    Debug.LogError(
                        $"DeleteSpritesFromAtlas Error , {atlasConfigWrapper.atlasName} not Contain {textureList[i].name} ");
                }
            }

            atlasConfigWrapper.InitTextures();
            EditorUtility.SetDirty(atlasConfigWrapper);
            AssetDatabase.SaveAssets();
        }

        public static void AddSpritesToAtlas(AtlasConfigWrapper atlasConfigWrapper, List<Texture> textureList)
        {
            for (int i = 0; i < textureList.Count; i++)
            {
                if (!atlasConfigWrapper.textureList.Contains(textureList[i]))
                {
                    atlasConfigWrapper.textureList.Add(textureList[i]);
                }
                else
                {
                    Debug.LogError("AtlasTools AddSpritesToAtlas Error :" + textureList[i].name + " 重复");
                }
            }

            atlasConfigWrapper.InitTextures();
            EditorUtility.SetDirty(atlasConfigWrapper);
            AssetDatabase.SaveAssets();
        }

        public static void CreateAllAtlas()
        {
            for (int i = 0; i < AtlasConfigWrappers.Count; i++)
            {
                CreateAtlas(AtlasConfigWrappers[i]);
            }
            // CreateAtlasConfigJson();
        }

        public static void CreateAtlas(AtlasConfigWrapper atlasConfigWrapper)
        {
            string atlasPath = $"{atlasDirPath}{atlasConfigWrapper.atlasName}.spriteatlas";
            SpriteAtlas atlas;
            if (File.Exists(atlasPath) == false)
            {
                atlas = new SpriteAtlas();
                AssetDatabase.CreateAsset(atlas, atlasPath);
                AssetDatabase.SaveAssets();
            }

            atlas = AssetDatabase.LoadAssetAtPath<SpriteAtlas>(atlasPath);
            var textureFiles = atlasConfigWrapper.textureList;
            UnityEngine.Object[] packables = atlas.GetPackables();

            SpriteAtlasPackingSettings setting = new SpriteAtlasPackingSettings();
            setting.enableRotation = false;
            setting.enableTightPacking = false;
            setting.padding = 4;
            atlas.SetPackingSettings(setting);
            atlas.Remove(packables);
            atlas.Add(textureFiles.ToArray());
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }

        static void CreateAtlasConfigJson()
        {
            try
            {
                AtlasJsonConfig config = new AtlasJsonConfig();
                config.atlases = new List<AtlasJsonConfig.AtlasData>();

                foreach (var wrapper in AtlasConfigWrappers)
                {
                    var atlasData = new AtlasJsonConfig.AtlasData
                    {
                        atlasName = wrapper.atlasName,
                        spriteAtlasPath = $"{atlasDirPath}{wrapper.atlasName}.spriteatlas",
                        sprites = wrapper.textureList.Select(t => t.name).ToList()
                    };
                    config.atlases.Add(atlasData);
                }

                string json = JsonUtility.ToJson(config, true);
                string configDir = Path.GetDirectoryName(atlasJsonConfig);
                if (!Directory.Exists(configDir))
                {
                    Directory.CreateDirectory(configDir);
                }
        
                File.WriteAllText(atlasJsonConfig, json);
                AssetDatabase.Refresh();
                Debug.Log($"图集配置文件已生成：{atlasJsonConfig}");
            }
            catch (Exception e)
            {
                Debug.LogError($"CreateAtlasConfigJson 错误: {e}");
            }
        }
    }

    [Serializable]
    public class AtlasJsonConfig
    {
        public List<AtlasData> atlases = new List<AtlasData>();

        [Serializable]
        public class AtlasData
        {
            public string atlasName;
            public string spriteAtlasPath;
            public List<string> sprites = new List<string>();
        }
    }
    
    public class AtlasSpriteInfo
    {
        public Texture texture;
        public string Name;
        public bool isSelected;
    }
}